import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import {
  HashRouter,
  BrowserRouter,
  useNavigate,
  useLocation,
  NavLink,
  Navigate,
  Outlet,
  useParams,
  Link,
  useRoutes,
} from "./my-react-router-dom";

const UserAPI = {
  list() {
    const usersStr = localStorage.getItem("users");
    const users = usersStr ? JSON.parse(usersStr) : [];
    return users;
  },
  add(user) {
    const users = UserAPI.list();
    users.push(user);
    localStorage.setItem("users", JSON.stringify(users));
  },
  find(id) {
    const users = UserAPI.list();
    return users.find((user) => user.id === id);
  },
};

function Home() {
  return <div>Home</div>;
}

function User() {
  return (
    <div>
      <ul>
        <li>
          <Link to="/user/list">用户列表</Link>
        </li>
        <li>
          <Link to="/user/add">添加用户</Link>
        </li>
      </ul>
      <div>
        <Outlet />
      </div>
    </div>
  );
}

function UserList() {
  const [users, setUsers] = React.useState([]);

  React.useEffect(() => {
    const users = UserAPI.list();
    setUsers(users);
  }, []);

  return (
    <ul>
      {users.map((user, index) => (
        <li key={index}>
          <Link to={`/user/detail/${user.id}`} state={user}>
            {user.name}
          </Link>
        </li>
      ))}
    </ul>
  );
}

function UserAdd() {
  const navigate = useNavigate();
  const nameRef = React.useRef();

  const handleSubmit = (event) => {
    event.preventDefault();
    const name = nameRef.current.value;
    UserAPI.add({ id: Date.now() + "", name });
    navigate("/user/list");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={nameRef} />
      <button type="submit">添加</button>
    </form>
  );
}

function UserDetail() {
  const location = useLocation();
  const { id } = useParams();
  const [user, setUser] = React.useState({});

  React.useEffect(() => {
    let user = location.state; // 取路径对象上的状态

    if (!user && id) {
      user = UserAPI.find(id);
    }

    if (user) setUser(user);
  }, []);

  return (
    <div>
      id: {user.id}
      <br />
      name: {user.name}
    </div>
  );
}

function Profile() {
  // 编程形式
  const navigate = useNavigate();
  const navigateTo = () => {
    navigate("/");
  };

  return (
    <div>
      Profile
      <button onClick={navigateTo}>跳转到/home</button>
    </div>
  );
}

function Login() {
  const navigation = useNavigate();
  const location = useLocation();

  const login = () => {
    localStorage.setItem("login", "true");
    let to = "/";
    if (location.state) {
      to = location.state.from || "/";
    }
    navigation(to);
  };

  return <button onClick={login}>登录</button>;
}

function getAuth() {
  return new Promise((resolve, rejected) => {
    setTimeout(() => {
      resolve(localStorage.getItem("login"));
    }, 2000);
  });
}

function Protected(props) {
  const { component: RouteComponent, path } = props;
  const [render, setRender] = useState(null);

  useEffect(() => {
    (async () => {
      const result = await getAuth();
      setRender(
        result ? (
          <RouteComponent />
        ) : (
          <Navigate to={{ pathname: "/login", state: { from: path } }} />
        )
      );
    })();
  }, []);

  return render;
}

function NotFound() {
  return <h1>Not Found</h1>;
}

// 某个组件的懒加载
const LazyPost = React.lazy(() => import("./Post"));

function BaseRouter() {
  const routers = [
    { path: "/", element: <Home /> },
    {
      path: "/user",
      element: <User />,
      children: [
        { path: "add", element: <UserAdd /> },
        { path: "list", element: <UserList /> },
        { path: "detail/:id", element: <UserDetail /> },
      ],
    },
    {
      path: "/profile",
      element: <Protected component={Profile} path="/profile" />,
    },
    { path: "/login", element: <Login /> },
    { path: "*", element: <NotFound /> },
  ];

  const [routes, setRoutes] = useState(routers);

  const addRoute = () => {
    setRoutes([
      ...routers,
      {
        path: "/post",
        element: (
          <React.Suspense fallback={<div>loading...</div>}>
            <LazyPost />
          </React.Suspense>
        ),
      },
    ]);
  };
  const element = useRoutes(routes);

  return (
    <>
      {element}
      <button onClick={addRoute}>动态添加路由</button>
    </>
  );
}

const App = () => {
  const activeNavProps = {
    style: ({ isActive }) => (isActive ? { backgroundColor: "green" } : {}),
    className: ({ isActive }) => (isActive ? "active" : ""),
  };

  return (
    <BrowserRouter>
      <NavLink end={true} to="/" {...activeNavProps}>
        Home
      </NavLink>
      <NavLink to="/login" {...activeNavProps}>
        Login
      </NavLink>

      <BaseRouter />
    </BrowserRouter>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
